package com.acme.bankapp.service.bank;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import com.acme.bankapp.domain.account.AbstractAccount;
import com.acme.bankapp.domain.account.CheckingAccount;
import com.acme.bankapp.domain.account.SavingsAccount;
import com.acme.bankapp.domain.bank.*;
import com.acme.bankapp.domain.client.Client;
import com.acme.bankapp.domain.client.Gender;
import com.acme.bankapp.domain.email.Email;
import com.acme.bankapp.domain.email.EmailException;
import com.acme.bankapp.domain.exception.BankException;
import com.acme.bankapp.domain.exception.ClientExistsException;
import com.acme.bankapp.domain.exception.NotEnoughFundsException;
import com.acme.bankapp.service.email.EmailService;
import com.acme.server.BankServer;


public class BankApplication {
	
	public static final String ALREADY_LOADED = "Bank has already been loaded via another program argument. Only one option from the list {-m, -lf, -l} may be specified at a time.";
	public static final String DEF_BANK_SER = "bank.ser";
	public static final String DEF_BANK_FEED = "bank.dat";
	
	private static BankDataLoaderService bankDataLoader;
	
	public static void addClient(Bank bank, Client client){
		
		try {
			BankService.addClient(bank, client);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
	}
	
	public static void withdraw(Client client, double sum){
		try {
			client.getAccount().withdraw(sum);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
	}

	public static void modifyBank(Bank bank){
		for (Client client : bank.getClients()) {
			withdraw(client, 100);
		}	
			
	}
	
	public static void addClientsTest(Bank bank){
		
		Client client1 = new Client("Ivanov", Gender.MALE, (new CheckingAccount(50, 100)));
		Client client2 = new Client("Petrova", Gender.FEMALE, (new CheckingAccount(30)));
		Client client3 = new Client("Ivanov", Gender.MALE, (new CheckingAccount(50, 100)));
		Client client4 =  new Client("Sidorov", Gender.MALE, (new SavingsAccount(100)));
		
		addClient(bank, client1);
		addClient(bank, client2);
		addClient(bank, client3);
		addClient(bank, client4);
		
	}
	
	public static void TestEqualsAndHashCode(){
		
		AbstractAccount testsaveac1 = new SavingsAccount(100);
		AbstractAccount testsaveac2 = new SavingsAccount(100);
		
		if(testsaveac1.equals(testsaveac2)){
			System.out.println(testsaveac1 + " equals " + testsaveac2);
			System.out.println(testsaveac1.hashCode());
			System.out.println(testsaveac2.hashCode());
		} else {
			System.out.println(testsaveac1 + " not equals " + testsaveac2);
		}			
				
		
		Client testclient1 = new Client("John", Gender.MALE, testsaveac1);
		Client testclient2 = new Client("Mira", Gender.FEMALE, testsaveac2);
		
		if(testclient1.equals(testclient2)){
			System.out.println(testclient1 + " equals " + testclient2);
		
		} else {
			System.out.println(testclient1 + " not equals " + testclient2);
		}	
		System.out.println("hashCode");
		System.out.println("testclient1 - " + testclient1.hashCode());
		System.out.println("testclient2 - " + testclient2.hashCode());
		
		if(testclient1.equals(testclient1)){
			System.out.println(testclient1 + " equals " + testclient1);
		}
		
		
	}
	
	private static void initServices() {
		bankDataLoader = new BankDataLoaderService();
	}

	private static void saveTheBankToDataSource(final Bank bank){
		try {
			BankService.saveBank(bank, BankApplication.DEF_BANK_SER);
		} catch (Exception e) {
			System.out.println("Save bank error " + e.getMessage());
		}
	}

	private static Bank loadBankFromDataSource(){
		Bank bank = null;
		try {
			bank = BankService.loadBank(BankApplication.DEF_BANK_SER);
		} catch (Exception e) {
			System.out.println("Read bank error " + e.getMessage());
		}
		return bank;
	}

	private static Bank loadBankFromFeed() throws IOException {
		initServices();
		Bank bank = BankService.createNewBank();
		bankDataLoader.load(bank, BankApplication.DEF_BANK_FEED);
		BankService.printBalance(bank);
		modifyBank(bank);
		
		saveTheBankToDataSource(bank);
		return bank;
	}

	private static Set<String> readArgs(String... args){
		Set<String> arguments = new HashSet<String>();
		for (String string : args) {
			arguments.add(string);
		}
		return arguments;
	}
	
	public static void main(String[] args) throws IOException{

		Set<String> arguments = readArgs(args);
		
		boolean bankLoaded = false;
		
		Bank bank = null;

		if (arguments.contains("-loadfeed")) {
			bank = loadBankFromFeed();
			bankLoaded = true;
		}

		if (arguments.contains("-loadbank")) {
			if (bankLoaded) {
				System.out.println(ALREADY_LOADED);
				return;
			}
			bank = loadBankFromDataSource();
			bankLoaded = true;
		}
		
		
		if (bank == null) {
			System.out.println("Bank is not loaded");
			return;
		}
		
		BankService.printBalance(bank);

		
		// Now we have a bank.
		if (arguments.contains("-server")) {
            BankServer bankServer = new BankServer();
            
            bankServer.startServer(bank);
		}
	}
}
